package net.lovesrc.allin.biz.lbc;

import com.alibaba.fastjson.JSONObject;
import com.zhouzhou.fastjava.BizException;
import com.zhouzhou.fastjava.http.HttpException;
import com.zhouzhou.fastjava.http.MyHttpRequest;
import com.zhouzhou.fastjava.http.Requests;
import com.zhouzhou.fastjava.util.StringKit;
import lombok.extern.slf4j.Slf4j;
import net.lovesrc.support.service.generator.bankcard.BankCardBinGenerate;
import net.lovesrc.support.service.generator.bankcard.BankCardNumberGenerator;
import net.lovesrc.support.service.generator.bankcard.BankCardTypeEnum;
import net.lovesrc.support.service.generator.bankcard.BankNameEnum;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.BasicCookieStore;
import org.jsoup.Jsoup;

import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * @author gelic
 * Created in 22:39 2019/2/21
 * @since
 */
@Slf4j
@Service
public class LbcRegisterService extends BaseLbcService {

    public String register(String promotionCode) {
        //0.访问邀请注册页,获取隐藏在页面中的_token
        if (StringUtils.isBlank(promotionCode)) {
            throw BizException.messageOf("无效的邀请码");
        }
        CookieStore cookieStore = new BasicCookieStore();
        HttpClient httpClient = newHttpClientWithMyProxy(null, cookieStore);
        String html = MyHttpRequest.get(httpClient, "https://www.bluebeicoin.com/register/" + promotionCode)
                .printResText(false)
                .executeUtilReturnAndWaitMillSecond(REQUEST_MILLSECOND_INTERVAL, 200)
                .asText();
        String formToken = Jsoup.parse(html)
                .body()
                .select("input[type=hidden]")
                .select("[name=_token]")
                .select("[value]")
                .first()
                .attr("value");

        //1. 准备用户名,手机号,登录密码,安全密码
        String mobile = doGetNewMobile();

        //2. 获取短信验证码(存表方便异常时使用?)
        JSONObject codeResJson = MyHttpRequest.post(httpClient, "https://www.bluebeicoin.com/send_code")
                .param("phone", mobile)
                .param("_token", formToken)
                .executeUtilReturnAndWaitMillSecond(REQUEST_MILLSECOND_INTERVAL, 200)
                .asJson();

        checkResJson(codeResJson);

        String verifyCode;
        try {
            verifyCode = getMobileVerifyCodeWrapper().getVerifyCodeFromPhone(mobile, 4);
        } catch (BizException e) {
            throw BizException.messageOf("未能获取到验证码");
        } finally {
            getMobileVerifyCodeWrapper().releasePhone(mobile);
        }

        String password = RandomStringUtils.randomAlphanumeric(6, 8);
        String payPassword = "356251";

        //3. 准备注册参数,注册
        JSONObject regResJson = MyHttpRequest.post(httpClient, "https://www.bluebeicoin.com/register")
                .param("_token", formToken)
                .param("name", mobile)
                .param("phone", mobile)
                .param("verification", verifyCode)
                .param("invcode", promotionCode)
                .param("password", password)
                .param("confirmed", password)
                .param("payPassword", payPassword)
                .param("confirmedPay", payPassword)
                .executeUtilReturnAndWaitMillSecond(REQUEST_MILLSECOND_INTERVAL, 200)
                .asJson();
        String status = regResJson.getString("status");
        if (!"success".equals(status)) {
            String message = regResJson.getString("message");
//            //邀请码无效,换一个
//            if (message.contains("无效的邀请码")) {
//            }
            if (message.contains("手机号已占用")) {
                getMobileVerifyCodeWrapper().addBlack(mobile);
            }
            throw BizException.messageOf(message);
        }

        //4. 保存数据
        JSONObject newRow = new JSONObject()
                .fluentPut("mobile", mobile)
                .fluentPut("verifyCode", verifyCode)
                .fluentPut("promotionCode", promotionCode)
                .fluentPut("password", password)
                .fluentPut("payPassword", payPassword)
                .fluentPut("registerResText", regResJson.toJSONString())
                .fluentPut("registerStatus", regResJson.getString("status"))
                .fluentPut("cookies", Requests.toCookieString(cookieStore));
        insertRow(jdbcTemplate, "t_lbc_account", newRow);

        //5. 更新邀请者的团队数和直邀数
        jdbcTemplate.update("update t_lbc_account set directRCount = directRCount + 1,teamCount = teamCount + 1 where inviteCode = ?", promotionCode);
        return mobile;
    }

    private String doGetNewMobile() {
        for (; ; ) {
            String mobile = getMobileVerifyCodeWrapper().getPhone();
            if (jdbcTemplate.queryForObject("select count(1) from t_lbc_account where mobile = ?", long.class, mobile) > 0) {
                getMobileVerifyCodeWrapper().addBlack(mobile);
                continue;
            }
            return mobile;
        }
    }

    public void authId(String mobile, Proxy proxy) {
        try {
            this.doAuthId(mobile, proxy);
        } catch (HttpException e) {
            logger.error("auth id warning, {}", mobile, e);
        } catch (Exception e) {
            logger.error("auth id error, {}", mobile, e);
            jdbcTemplate.update("update t_lbc_account set idStatus = 'failure', idTime = ?, idErrorMsg = ? where mobile = ?", new Date(), ExceptionUtils.getMessage(e), mobile);
        }
    }

    public synchronized void doAuthId(String mobile, Proxy proxy) {
        JSONObject row = getAndCheckRow(mobile);
        String idStatus = row.getString("idStatus");
        if ("success".equalsIgnoreCase(idStatus)) {
            return;
        }
        if ("submitted".equalsIgnoreCase(idStatus)) {
            return;
        }
        // 准备身份认证信息,姓名,idcard,手机号,银行卡号,银行名字,支付号,微信
        JSONObject idRow = getFreeIdCard();
        String realName = idRow.getString("realName");
        String idCardNumber = idRow.getString("idCardNumber");

        BankNameEnum[] names = {BankNameEnum.ICBC, BankNameEnum.ABC, BankNameEnum.BOC, BankNameEnum.CCB, BankNameEnum.BCOM};
        BankCardBinGenerate.BankCardBin bankCardBin = BankCardBinGenerate.generate(names[new Random().nextInt(names.length)], BankCardTypeEnum.DEBIT);
        String bankName = bankCardBin.getTitle();
        String bankCardNumber;
        for (; ; ) {
            bankCardNumber = BankCardNumberGenerator.generateByBankCardBin(bankCardBin);
            if (jdbcTemplate.queryForObject("select count(1) from t_lbc_account where bankCardNumber = ?", long.class, bankCardNumber) == 0) {
                break;
            }
        }

        String formToken = getFormToken(mobile, "https://www.bluebeicoin.com/user/authenticate", proxy);
        // 认证
        JSONObject resJson = post2Json(mobile, "https://www.bluebeicoin.com/user/authenticate",
                new JSONObject()
                        .fluentPut("_token", formToken)
                        .fluentPut("name", realName)
                        .fluentPut("idCard", idCardNumber)
                        .fluentPut("phone", mobile)
                        .fluentPut("bank_code", bankCardNumber)
                        .fluentPut("cardName", bankName)
                        .fluentPut("alipay", mobile)
                        .fluentPut("wechat", mobile),
                proxy);

        checkResJson(resJson);

        JSONObject sets = new JSONObject()
                .fluentPut("idResText", resJson.toJSONString())
                .fluentPut("idCardNumber", idCardNumber)
                .fluentPut("realName", realName)
                .fluentPut("idStatus", "submitted")
                .fluentPut("idTime", new Date())
                .fluentPut("idResStatus", resJson.getString("status"))
                .fluentPut("bankCardNumber", bankCardNumber)
                .fluentPut("bankName", bankName)
                .fluentPut("alipay", mobile)
                .fluentPut("wechat", mobile);
        updateRow(jdbcTemplate, "t_lbc_account", sets, "mobile = ?", mobile);
    }

    private JSONObject getFreeIdCard() {
        String sql = "select * from t_id_card where worked = 1 and frontOcrStatus = 'normal' and backOcrStatus = 'normal' " +
                " and idCardNumber not in (select idCardNumber from t_lbc_account where idCardNumber is not null) " +
                " order by rand() limit 1";
        JSONObject row = queryForRow(jdbcTemplate, sql);
        if (row == null) {
            throw BizException.messageOf("无可用的身份证信息了");
        }
        return row;
    }

    public void doSyncStatus(String mobile, Proxy proxy) {
        JSONObject row = getAndCheckRow(mobile);
        String idStatus = row.getString("idStatus");
        if ("success".equalsIgnoreCase(idStatus)) {
            return;
        }
        if (StringKit.notEqualsIgnoreCase("submitted", idStatus)) {
            return;
        }
        // 矿机
        List<JSONObject> kjs = getMyKjs(mobile, proxy);
        if (kjs.size() > 0) {
            jdbcTemplate.update("update t_lbc_account set idStatus = 'success', idSuccessTime = ? where mobile = ?", new Date(), mobile);
            onAuthIdSuccess(mobile, proxy);
        } else {
            throw BizException.messageOf("暂无矿机");
        }
    }

    private void onAuthIdSuccess(String mobile, Proxy proxy) {
        String resStr = get2Text(mobile, "https://www.bluebeicoin.com/user/invite", proxy);
        //https://www.bluebeicoin.com/register/86261837
        String inviteUrl = Jsoup.parse(resStr)
                .getElementById("text")
                .attr("value");
        String inviteCode = inviteUrl.substring(inviteUrl.lastIndexOf("/") + 1);
        updateRow(jdbcTemplate, "t_lbc_account", new JSONObject().fluentPut("inviteCode", inviteCode).fluentPut("profitTime", new Date()), "mobile = ?", mobile);
    }

    public void syncStatus(String mobile, Proxy proxy) {
        try {
            this.doSyncStatus(mobile, proxy);
        } catch (HttpException e) {
            logger.error("auth id warning, {}", mobile, e);
        } catch (Exception e) {
            logger.error("sync auth id error, {}", mobile, e);
            jdbcTemplate.update("update t_lbc_account set idStatus = 'sync-failure', idTime = ?, idErrorMsg = ? where mobile = ?", new Date(), ExceptionUtils.getMessage(e), mobile);
        }
    }

}
